﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Data.OleDb;
using System.Data;
using MyClass;

namespace GPS_DB
{
    public class GpsMapImg
    {
        #region Setting
        private const int MINDIVISOR = 15, MAXDIVISOR = 500000;
        private const int INFO_POINT_NUM_MAX = 51000;
        private const int SCALEMAX = 20*9000;//1km = 9000(0.0001度)   1km = 540(0.001分) (不是度)
        
        public int ImgWidth = 1500, ImgHeight = 900;
        #endregion


        #region Inner Variables

        private int MinLon = 120000000, MaxLon = 120000000;
        private int Minlat = 40000000, MaxLat = 40000000;
        private struct StationType
        {
            public int latDimi;/// 0.0001 Degree
            public int lonDimi;/// 0.0001 Degree
            public string stationName;
            public string roadName;
            public string dispatchName;
            public string mode;
            public string sPhone;
            public string xPhone;
            public int LengthDini;
            public int WidthDini;
            public int[] nextStationOffset;
        }
        private int stationNumber;
        private ArrayList stations = new ArrayList();
        private ArrayList stationsOfSelectedRoad = new ArrayList();

        private struct QieHuangType
        {
            public string longitude;
            public string latitude;
            public string width;
            public string line1;
            public string dispatch1;
            public string line2;
            public string dispatch2;
        }
        private int qiehuangNumber;
        private ArrayList qiehuangs = new ArrayList();

        private struct RegionType
        {
            public string longitude;
            public string latitude;
            public string lonwidth;
            public string latwidth;
            public string lineItem;
        }
        private int regionNumber;
        private ArrayList regions = new ArrayList();

        private struct RoadType
        {
            public string roadName;
            public string dispatchName;
        }
        private int dispatchNumber;
        private ArrayList dispatchs = new ArrayList();

        private int[] infoPlon = new int[INFO_POINT_NUM_MAX];
        private int[] infoPlat = new int[INFO_POINT_NUM_MAX];
        private int infoNumber;

        private bool stationNameChecked;
        private bool selectAllroad;
        private bool selectConnect;
        private bool selectSwitch;
        private bool selectRegion;
        private bool selectScale;
        private string selectedRoadName;

        private int divisor;
        private int centerlon;
        private int centerlat;

        private long startTick;

        #endregion

        #region User Variables
        public Image GPS_DB_IMG;
        public Image Train_IMG = new Bitmap(10, 10);
        public int Train_lon;
        public int Train_lat;

        public bool StationNameChecked
        {
            set
            {
                stationNameChecked = value;
            }
            get
            {
                return stationNameChecked;
            }
        }
        public bool SelectAllRoad
        {
            set
            {
                selectAllroad = value;
            }
            get
            {
                return selectAllroad;
            }
        }
        public bool SelectConnect
        {
            set
            {
                selectConnect = value;
            }
            get 
            {
                return selectConnect;
            }
        }
        public bool SelectSwitch
        {
            set
            {
                selectSwitch = value;
            }
            get
            {
                return selectSwitch;
            }
        }
        public bool SelectRegion
        {
            set
            {
                selectRegion = value;
            }
            get
            {
                return selectRegion;
            }
        }
        public bool SelectScale
        {
            set
            {
                selectScale = value;
            }
            get
            {
                return selectScale;
            }
        }

        public int Divisor
        {
            set
            {
                if (value >= MINDIVISOR && value <= MAXDIVISOR)
                    divisor = value;
            }
            get
            {
                return divisor;
            }

        }
        public int CenterLon
        {
            set
            {
                if (value < MinLon)
                    centerlon = MinLon;
                else if (value > MaxLon)
                    centerlon = MaxLon;
                else
                    centerlon = value;
            }
            get
            {
                return centerlon;
            }
        }
        public int CenterLat
        {
            set
            {
                if (value < Minlat)
                    centerlat = Minlat;
                else if (value > MaxLat)
                    centerlat = MaxLat;
                else
                    centerlat = value;
            }
            get
            {
                return centerlat;
            }
        }
        #endregion




        #region Inner Method
        private int xAxis(int x)
        {
            return x + ImgWidth / 2;
        }
        private int yAxis(int y)
        {
            return ImgHeight / 2 - y;
        }
        private float frontSize(int curDivisor)
        {
            float s = MAXDIVISOR / 100 / curDivisor * 0.25f + 7;
            if (s > 14)
                s = 16f;
            return s;
        }
        private void DrawStation(ArrayList stArray, bool isSelt)
        {
            Graphics g = Graphics.FromImage(GPS_DB_IMG);

            int stwidth_lon,stwidth_lat, x1, y1, x2, y2, offset_lon,offset_lat;
            int scale = SCALEMAX / Divisor;
            float mySize = frontSize(divisor);
            Font myfont = new Font("Arial", mySize);
            SolidBrush mybrush = new SolidBrush(Color.White);
            Pen mypen = Pens.White;


            int intlon1, intlat1, intlon2, intlat2;
            StationType st1;
            StationType st2;

            int j;

            #region customPen
            GraphicsPath hPath = new GraphicsPath();
            int arrowWidth = 10, arrowHeight = 16, head = 0;
            hPath.AddLine(new Point(0, -arrowHeight - head), new Point(arrowWidth / 2, -arrowHeight - head));
            hPath.AddLine(new Point(arrowWidth / 2, -arrowHeight - head), new Point(0, -head));
            hPath.AddLine(new Point(0, -head), new Point(-arrowWidth / 2, -arrowHeight - head));
            hPath.CloseFigure();
            CustomLineCap HookCap = new CustomLineCap(hPath, null);
            HookCap.SetStrokeCaps(LineCap.Round, LineCap.Round);
            Pen customCapPen = new Pen(Color.White, 1f);
            customCapPen.CustomEndCap = HookCap;
            //customCapPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
            //customCapPen.DashPattern = new float[] { 10, 100 };
            #endregion

            #region roadName check and set Pen
            if (stArray.Count > 0)
            {
                st1 = (StationType)stArray[0];
                if (st1.roadName != selectedRoadName && !selectAllroad)
                    return;
            }
            #endregion

            #region main loop for stArray.cout times
            for (int i = 0; i < stArray.Count; i++)
            {
                st1 = (StationType)stArray[i];
                if (isSelt)
                {
                    if (st1.mode == "101")
                    {
                        mypen = Pens.Green;
                        customCapPen = new Pen(Color.Green, 1f);
                        customCapPen.CustomEndCap = HookCap;
                    }
                    else
                    {
                        mypen = Pens.Purple;
                        customCapPen = new Pen(Color.Purple, 1f);
                        customCapPen.CustomEndCap = HookCap;
                    }
                }

                intlon1 = st1.lonDimi;
                intlat1 = st1.latDimi;
                intlon1 = intlon1 - centerlon;
                intlat1 = intlat1 - centerlat;
                stwidth_lon = st1.LengthDini;
                stwidth_lat = st1.WidthDini;
                x1 = intlon1 / divisor;
                y1 = intlat1 / divisor;
                offset_lon = stwidth_lon / divisor;
                offset_lat = stwidth_lat / divisor;

                if (Math.Abs(x1) < ImgWidth / 2 && Math.Abs(y1) < ImgHeight / 2)
                {
                    #region station
                    g.DrawRectangle(mypen, xAxis(x1 - offset_lon), yAxis(y1 + offset_lat), offset_lon * 2 + 1, offset_lat * 2 + 1);
                    #endregion

                    #region scale
                    if (selectScale)
                        g.DrawEllipse(mypen, xAxis(x1 - scale), yAxis(y1 + scale), scale * 2, scale * 2);
                    #endregion

                    #region name
                    if (stationNameChecked && divisor < 1500 && st1.stationName != "***")
                    {
                        g.DrawString(st1.stationName, myfont, mybrush, xAxis(x1 - offset_lon), yAxis(y1 - offset_lat));
                    }
                    #endregion
                }

                #region connection
                for (j = 0; j < 4 && selectConnect; j++)
                {
                    if (st1.nextStationOffset[j] == 0)
                        continue;
                    if (i + st1.nextStationOffset[j] < 0)
                        continue;
                    if (i + st1.nextStationOffset[j] >= stArray.Count)
                        continue;
                    st2 = (StationType)stArray[i + (st1.nextStationOffset[j] % 10000)];
                    intlon2 = st2.lonDimi;
                    intlat2 = st2.latDimi;
                    intlon2 -= centerlon;
                    intlat2 -= centerlat;
                    x2 = intlon2 / divisor;
                    y2 = intlat2 / divisor;

                    if ((Math.Abs(x1) < ImgWidth && Math.Abs(y1) < ImgHeight) ||
                        (Math.Abs(x2) < ImgWidth && Math.Abs(y2) < ImgHeight))
                    {
                        if (divisor < 100)
                        {
                            g.DrawLine(customCapPen, xAxis(x1), yAxis(y1), xAxis(x2), yAxis(y2));
                        }
                        else
                            g.DrawLine(mypen, xAxis(x1), yAxis(y1), xAxis(x2), yAxis(y2));
                    }

                }
                #endregion
            }
            #endregion

            g.Dispose();
        }
        private void DrawInfoPoint()
        {
            int intlon, intlat;
            Graphics g = Graphics.FromImage(GPS_DB_IMG);

            for (int i = 0; i < infoNumber; i++)
            {
                intlon = infoPlon[i];
                intlat = infoPlat[i];
                intlon -= centerlon;
                intlat -= centerlat;
                g.DrawRectangle(Pens.Gray, intlon / divisor + ImgWidth / 2, ImgHeight / 2 - intlat / divisor, 1, 1);
            }

            g.Dispose();
        }
        private void DrawRegion()
        {
            int i, intlon, intlat, regionLonW, regionLatW;
            Graphics g = Graphics.FromImage(GPS_DB_IMG);

            RegionType rg;
            for (i = 0; i < regionNumber && selectRegion; i++)
            {
                rg = (RegionType)regions[i];
                if (!rg.lineItem.Contains(selectedRoadName))
                {
                    if (!selectAllroad)
                        continue;
                }
                intlon = GF.ToDimiDegree(rg.longitude);
                intlat = GF.ToDimiDegree(rg.latitude);
                intlon -= centerlon;
                intlat -= centerlat;
                regionLonW = int.Parse(rg.lonwidth) * 100 / 6;
                regionLatW = int.Parse(rg.latwidth) * 100 / 6;
                g.DrawRectangle(Pens.Red, (intlon - regionLonW) / divisor + ImgWidth / 2, ImgHeight / 2 - (intlat + regionLatW) / divisor,
                                regionLonW * 2 / divisor + 1, regionLatW * 2 / divisor + 1);

            }
            g.Dispose();
        }
        private void DrawQieHuang()
        {
            int i, intlon, intlat, qiehuangW;
            Graphics g = Graphics.FromImage(GPS_DB_IMG);
            QieHuangType qh;
            for (i = 0; i < qiehuangNumber && selectSwitch; i++)
            {
                qh = (QieHuangType)qiehuangs[i];
                if (qh.line1 != selectedRoadName && qh.line2 != selectedRoadName)
                {
                    if (!selectAllroad)
                        continue;
                }

                intlon = GF.ToDimiDegree(qh.longitude);
                intlat = GF.ToDimiDegree(qh.latitude);
                intlon -= centerlon;
                intlat -= centerlat;
                qiehuangW = int.Parse(qh.width) * 100 / 6;
                g.DrawRectangle(Pens.Yellow, xAxis((intlon - qiehuangW) / divisor), yAxis((intlat + qiehuangW) / divisor),
                                qiehuangW * 2 / divisor + 1, qiehuangW * 2 / divisor + 1);
            }

            g.Dispose();

            
        }
        private void drawTimeUsed()
        {
            long tUsed = DateTime.Now.Ticks - startTick;
            float f = (float)tUsed / 10000000;
            Graphics g = Graphics.FromImage(GPS_DB_IMG);
            g.DrawString("GPS", new Font("Arial", 16), new SolidBrush(Color.DimGray), 250 + 10, 150 + 10);
            g.DrawString(f.ToString(), new Font("Arial", 8), new SolidBrush(Color.DimGray), 250 + 10, 150 + 30);
            g.Dispose();
        }
        private void FindTooFarStation()
        {
            int i;
            int intlon1, intlat1, intlon2, intlat2;
            long dis;

            string fileDir = Application.StartupPath + "\\temp\\";
            if (!Directory.Exists(fileDir))
                Directory.CreateDirectory(fileDir);

            string pathstr = Application.StartupPath + "\\temp\\" + "InformationPoint Searching.txt";
            if (File.Exists(pathstr))
            {
                File.Delete(pathstr);
            }

            using (FileStream fs1 = new FileStream(pathstr, FileMode.Create, FileAccess.ReadWrite))
            {
                StreamWriter w1 = new StreamWriter(fs1);
                for (i = 1; i < stationNumber - 1; i++)
                {
                    StationType st1, st2;
                    st1 = (StationType)stations[i];
                    st2 = (StationType)stations[i + 1];
                    if (st1.roadName == st2.roadName)
                    {
                        intlon1 = st1.lonDimi / 10;
                        intlat1 = st1.latDimi / 10;
                        intlon1 = intlon1 * 6 / 10;
                        intlat1 = intlat1 * 6 / 10;
                        intlon2 = st2.lonDimi / 10;
                        intlat2 = st2.latDimi / 10;
                        intlon2 = intlon2 * 6 / 10;
                        intlat2 = intlat2 * 6 / 10;
                        dis = (long)Math.Abs(intlon1 - intlon2) * (long)Math.Abs(intlon1 - intlon2) +
                              (long)Math.Abs(intlat1 - intlat2) * (long)Math.Abs(intlat1 - intlat2);
                        if (dis > (SCALEMAX / 10 * 6 / 10 * 2) * (SCALEMAX / 10 * 6 / 10 * 2) / 100 * 90)
                        {
                            w1.WriteLine(i.ToString() + ":" + st1.roadName.PadRight(10, ' ') +
                                        " " + st1.stationName + "-" + st2.stationName);
                        }
                    }
                }
                w1.Close();
                fs1.Close();
            }
            return;
        }
        private void setStartTime()
        {
            startTick = DateTime.Now.Ticks;
        }
        private void imgClear()
        {
            Graphics g = Graphics.FromImage(GPS_DB_IMG);
            g.Clear(Color.Black);
            g.Dispose();
        }
        #endregion

        #region User Method
        public GpsMapImg()
        {
            GPS_DB_IMG = new Bitmap(ImgWidth, ImgHeight);
            selectedRoadName = "";
            selectRegion = true;
            selectSwitch = true;
            selectAllroad = true;
            selectConnect = true;
            stationNameChecked = true;
            stationNumber = 0;
            divisor = 50000;
            centerlat = 33000000;
            centerlon = 110000000;

            stationNumber = 0;
            stations.Clear();
            qiehuangNumber = 0;
            infoNumber = 0;

            qiehuangs.Clear();
            regionNumber = 0;
            regions.Clear();
        }
        public void TrainImgSetColor(Color c)
        {
            Graphics h = Graphics.FromImage(Train_IMG);
            h.Clear(c);
            h.Dispose();
        }
        public void GPS_DB_IMG_SizeChange(int w,int h)
        {
            ImgWidth = w;
            ImgHeight = h;
            GPS_DB_IMG.Dispose();
            GPS_DB_IMG = new Bitmap(w, h);
            CreatGPS_DB_IMG();
        }
        public void CreatGPS_DB_IMG()
        {
            imgClear();

            setStartTime();

            DrawStation(stations, false);

            DrawStation(stationsOfSelectedRoad, true);

            DrawInfoPoint();

            DrawRegion();

            DrawQieHuang();

            drawTimeUsed();
        }
        /// <summary>
        /// Read in Database for map
        /// </summary>
        /// <param name="path">Directory of the Database(xls/xlsx) file</param>
        public void ReadInXLS(string path)
        {
            DataSet ds = null;
            try
            {
                ds = GF.DsFromExcel(path);
            }
            catch (Exception er)
            {
                throw new Exception(er.Message);
            }

            #region station
            stationNumber = ds.Tables["车站$"].Rows.Count;
            int[] stationID = new int[stationNumber];
            int[,] next=new int[stationNumber,4];
            stations.Clear();
            StationType st = new StationType();
            
            if (ds.Tables.Contains("车站$"))
            {
                #region read in
                for (int count = 0; count < ds.Tables["车站$"].Rows.Count; count++)
                {
                    if(!GF.IsEmpty(ds.Tables["车站$"].Rows[count][0]))
                    {
                        st.nextStationOffset = new int[4];
                        for (int i = 0; i < 4; i++)
                        {
                            st.nextStationOffset[i] = 0;
                        }
                        st.roadName = ds.Tables["车站$"].Rows[count][0].ToString().Trim();
                        st.dispatchName = ds.Tables["车站$"].Rows[count][1].ToString().Trim();
                        st.mode = ds.Tables["车站$"].Rows[count][2].ToString().Trim();
                        st.stationName = ds.Tables["车站$"].Rows[count][3].ToString().Trim();
                        st.sPhone = ds.Tables["车站$"].Rows[count][5].ToString().Trim();
                        st.xPhone = ds.Tables["车站$"].Rows[count][6].ToString().Trim();
                        st.lonDimi = GF.ToDimiDegree(ds.Tables["车站$"].Rows[count][7].ToString().Trim());
                        st.latDimi = GF.ToDimiDegree(ds.Tables["车站$"].Rows[count][8].ToString().Trim());
                        GF.refreshRange(ref MinLon, ref MaxLon, st.lonDimi);
                        GF.refreshRange(ref Minlat, ref MaxLat, st.latDimi);
                        st.LengthDini = int.Parse(ds.Tables["车站$"].Rows[count][10].ToString().Trim()) * 100 / 6;
                        st.WidthDini = int.Parse(ds.Tables["车站$"].Rows[count][11].ToString().Trim()) * 100 / 6;
                        stations.Add(st);
                        stationID[count] = int.Parse(ds.Tables["车站$"].Rows[count][4].ToString().Trim());
                        for (int i = 0; i < 4; i++)
                        {
                            next[count,i] = int.Parse(ds.Tables["车站$"].Rows[count][18 + i].ToString().Trim());
                        }
                    }
                    else
                        break;
                }
                stationNumber = stations.Count;
                #endregion

                #region find next station offset
                for (int count = 0; count < stationNumber; count++)
                {
                    StationType stTemp = (StationType)stations[count];

                    #region station
                    for (int i = 0; i < 4 && stationID[count] != 0; i++)
                    {
                        #region invalid next station
                        if (next[count, i] == 0 || next[count, i] == stationID[count])
                            continue;
                        #endregion

                        bool nextSation = false;

                        #region up direction connection
                        if (GF.IndexInArray(stationID,stationNumber,next[count, i]) < count)
                        {
                            bool passStation = false;
                            for (int j = 1; count - j >= 0; j++)
                            {
                                if (stationID[count - j] != 0)
                                    passStation = true;

                                bool sameNxt = false;
                                bool nxtIsMe = false;
                                for (int k = 0; k < 4; k++)
                                {
                                    if (next[count, i] == next[count - j, k])
                                        sameNxt = true;
                                    if (stationID[count] == next[count - j, k])
                                        nxtIsMe = true;

                                }
                                if (sameNxt && nxtIsMe && stationID[count-j]==0)
                                {
                                    nextSation = true;
                                    stTemp.nextStationOffset[i] = -j;
                                    break;
                                }
                                if (sameNxt && !passStation)
                                {
                                    nextSation = true;
                                    stTemp.nextStationOffset[i] = -j;
                                    break;
                                }
                                if (next[count, i] == stationID[count - j])
                                {
                                    nextSation = true;
                                    stTemp.nextStationOffset[i] = -j;
                                    break;
                                }
                            }
                        }
                        #endregion

                        #region down direction connection
                        else
                        {
                            bool passStation = false;
                            for (int j = 1; count + j < stationNumber; j++)
                            {
                                if (stationID[count + j] != 0)
                                    passStation = true;

                                bool sameNxt = false;
                                bool nxtIsMe = false;
                                for (int k = 0; k < 4; k++)
                                {
                                    if (next[count, i] == next[count + j, k])
                                        sameNxt = true;
                                    if (stationID[count] == next[count + j, k])
                                        nxtIsMe = true;

                                }
                                if (sameNxt && nxtIsMe && stationID[count + j]==0)
                                {
                                    nextSation = true;
                                    stTemp.nextStationOffset[i] = j;
                                    break;
                                }
                                if (sameNxt && !passStation)
                                {
                                    nextSation = true;
                                    stTemp.nextStationOffset[i] = j;
                                    break;
                                }
                                if (next[count, i] == stationID[count + j])
                                {
                                    nextSation = true;
                                    stTemp.nextStationOffset[i] = j;
                                    break;
                                }
                            }
                        }
                        #endregion

                        if (!nextSation)
                        {
                            MessageBox.Show("没有找到前站 of Row: " + count.ToString() + " => " + next[count, i].ToString());
                        }
                    }
                    #endregion

                    #region information point
                    for (int i = 0; i < 4 && stationID[count] == 0; i++)
                    {
                        #region invalid next station
                        if (next[count, i] == 0 || next[count, i] == stationID[count])
                            continue;
                        #endregion

                        bool nextSation = false;

                        #region connection
                        int nextcount;
                        bool singleDirct = true;
                        //bool passStation = false;
                        bool upDirection = false;
                        if (GF.IndexInArray(stationID, stationNumber, next[count, i]) < count)
                            upDirection = true;
                        for (int j = 1; true; j++)
                        {
                            if (upDirection)
                            {
                                nextcount = count - j;
                                if (nextcount < 0)
                                    break;
                            }
                            else
                            {
                                nextcount = count + j;
                                if (nextcount >= stationNumber)
                                    break;
                            }
                            //if (stationID[nextcount] != 0)
                            //        passStation = true;

                            bool doubleConn = GF.GPS_DB_DoubleConn(next, count, nextcount);
                            bool sameNxt = GF.GPS_DB_IsOneOfThem(next, nextcount, next[count, i]);
                            bool isInfo = false;
                            if (stationID[nextcount] == 0)
                                isInfo = true;

                            int offset = j;
                            if (upDirection)
                                offset = -j;

                            if (isInfo && sameNxt && singleDirct)
                            {
                                nextSation = true;
                                stTemp.nextStationOffset[i] = offset;
                                break;
                            }
                            if (isInfo && sameNxt && !singleDirct && doubleConn)
                            {
                                nextSation = true;
                                stTemp.nextStationOffset[i] = offset;
                                break;
                            }

                            if (next[count, i] == stationID[nextcount])
                            {
                                nextSation = true;
                                stTemp.nextStationOffset[i] = offset;
                                break;
                            }
                            if (GF.GPS_DB_NextNum(next, nextcount) > 1)
                                singleDirct = false;
                        }
                        #endregion

                        if (!nextSation)
                        {
                            MessageBox.Show("没有找到前站 of Row: " + count.ToString() + " => " + next[count, i].ToString());
                        }
                    }
                    #endregion

                    stations.RemoveAt(count);
                    stations.Insert(count, stTemp);
                }
                #endregion
            }
            #endregion

            #region switch
            qiehuangs.Clear();
            QieHuangType qh = new QieHuangType();
            if (ds.Tables.Contains("切换点$"))
            {
                for (int count = 0; count < ds.Tables["切换点$"].Rows.Count; count++)
                {
                    if (!GF.IsEmpty(ds.Tables["切换点$"].Rows[count][0]))
                    {
                        qh.longitude    = ds.Tables["切换点$"].Rows[count][0].ToString().Trim();
                        qh.latitude     = ds.Tables["切换点$"].Rows[count][1].ToString().Trim();
                        qh.line1        = ds.Tables["切换点$"].Rows[count][2].ToString().Trim();
                        qh.dispatch1    = ds.Tables["切换点$"].Rows[count][3].ToString().Trim();
                        qh.line2        = ds.Tables["切换点$"].Rows[count][4].ToString().Trim();
                        qh.dispatch2    = ds.Tables["切换点$"].Rows[count][5].ToString().Trim();
                        qh.width = ds.Tables["切换点$"].Rows[count][6].ToString().Trim();
                        qiehuangs.Add(qh);
                    }
                    else
                        break;
                }
            }
            #endregion

            #region region
            regions.Clear();
            RegionType rg = new RegionType();
            if (ds.Tables.Contains("线路选择区间$"))
            {
                for (int count = 0; count < ds.Tables["线路选择区间$"].Rows.Count; count++)
                {
                    if (!GF.IsEmpty(ds.Tables["线路选择区间$"].Rows[count][0]))
                    {
                        rg.longitude = ds.Tables["线路选择区间$"].Rows[count][1].ToString().Trim();
                        rg.latitude = ds.Tables["线路选择区间$"].Rows[count][2].ToString().Trim();
                        rg.lonwidth = ds.Tables["线路选择区间$"].Rows[count][19].ToString().Trim();
                        rg.latwidth = ds.Tables["线路选择区间$"].Rows[count][20].ToString().Trim();
                        rg.lineItem = "";
                        for (int i = 0; i < 8; i++)
                        {
                            string temp1 = ds.Tables["线路选择区间$"].Rows[count][3 + i * 2].ToString().Trim();
                            string temp2 = ds.Tables["线路选择区间$"].Rows[count][4 + i * 2].ToString().Trim();
                            if (temp1 != "")
                            {
                                rg.lineItem += temp1.PadRight(5, '　') + temp2 + "\r\n";
                            }
                        }
                        regions.Add(rg);
                    }

                    else
                        break;
                }
            }
            #endregion

            #region road
            dispatchs.Clear();
            RoadType rd = new RoadType();
            if (ds.Tables.Contains("线路调度区段$"))
            {
                for (int count = 0; count < ds.Tables["线路调度区段$"].Rows.Count; count++)
                {
                    if (!GF.IsEmpty(ds.Tables["线路调度区段$"].Rows[count][0]))
                    {
                        rd.roadName = ds.Tables["线路调度区段$"].Rows[count][2].ToString().Trim();
                        rd.dispatchName = ds.Tables["线路调度区段$"].Rows[count][3].ToString().Trim();
                        dispatchs.Add(rd);
                    }
                    else
                        break;
                }
            }
            #endregion

            dispatchNumber = dispatchs.Count;
            qiehuangNumber = qiehuangs.Count;
            regionNumber = regions.Count;

            FindStationsOfSelectedRoad(selectedRoadName);

            FindTooFarStation();

        }
        public void ReadInXLSPoint()
        {
            infoNumber = 0;
            OpenFileDialog frm1 = new OpenFileDialog();
            frm1.Filter = "所有数据(.xlsx)|*.xlsx";
            frm1.Title = "Please select the primary data(xls) file";
            frm1.Multiselect = true;
            frm1.RestoreDirectory = true;
            frm1.InitialDirectory = LrnS.GetItem("xlspointFilePath");
            if (frm1.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("xlspointFilePath", Path.GetDirectoryName(frm1.FileName));
                foreach (string fn in frm1.FileNames)
                {
                    DataSet ds = null;
                    try
                    {
                        ds = GF.DsFromExcel(fn);
                    }
                    catch (Exception er)
                    {
                        throw new Exception(er.Message);
                    }
                    int numrows = ds.Tables["sheet1$"].Rows.Count;
                    for (int i = 0; i < numrows; i++)
                    {
                        infoPlon[infoNumber] = GF.ToDimiDegree(ds.Tables["sheet1$"].Rows[i][0].ToString().Trim()); ;
                        infoPlat[infoNumber] = GF.ToDimiDegree(ds.Tables["sheet1$"].Rows[i][1].ToString().Trim());
                        infoNumber++;
                        if (infoNumber >= INFO_POINT_NUM_MAX)
                        {
                            MessageBox.Show("To many data");
                            return;
                        }
                    }
                }
            }
        }
        public void ReadInMDBPoint()
        {
            infoNumber = 0;
            OpenFileDialog frm1 = new OpenFileDialog();
            frm1.Filter = "所有数据(.mdb)|*.mdb" +
                            "|(.mdb)|" + selectedRoadName + "(*.mdb" +
                                   ";" + selectedRoadName + "R*.mdb";
            frm1.FilterIndex = 2;
            if (selectedRoadName == "")
                frm1.FilterIndex = 1;
            frm1.Title = "Please select the primary data(MDB) file";
            frm1.Multiselect = true;
            frm1.RestoreDirectory = true;
            frm1.InitialDirectory = LrnS.GetItem("mdbFilePath");
            if (frm1.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("mdbFilePath", Path.GetDirectoryName(frm1.FileName));
                foreach (string fn in frm1.FileNames)
                {
                    string connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fn;
                    OleDbConnection conn = new OleDbConnection(connstr);
                    OleDbDataAdapter dscmd = new OleDbDataAdapter();
                    DataSet resultdataset = new DataSet();

                    string strselect = "Select 经度,纬度,所属线路名称 From export Order By 序号 Desc";
                    OleDbCommand selectcommand = new OleDbCommand(strselect, conn);
                    selectcommand.CommandType = CommandType.Text;

                    try
                    {
                        conn.Open();

                        dscmd.SelectCommand = selectcommand;
                        int numrows = dscmd.Fill(resultdataset, "export");

                        if (numrows > 0)
                        {
                            for (int i = 0; i < numrows; i++)
                            {
                                infoPlon[infoNumber] = GF.ToDimiDegree(resultdataset.Tables["export"].Rows[i]["经度"].ToString());
                                infoPlat[infoNumber] = GF.ToDimiDegree(resultdataset.Tables["export"].Rows[i]["纬度"].ToString());
                                infoNumber++;
                                if (infoNumber >= INFO_POINT_NUM_MAX)
                                {
                                    MessageBox.Show("To many data");
                                    return;
                                }
                            } 
                        }
                        else
                        {
                            MessageBox.Show("未找到有效数据！");
                        }
                    }
                    catch (Exception er)
                    {
                        MessageBox.Show("MDB Opening Error: "+er.Message.ToString());
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }
        public void ReadInSimulationFile(string path)
        {
            infoNumber = 0;
            using (TextReader fs = File.OpenText(path))
            {
                string readStr = "";

                readStr = fs.ReadLine();//unused
                readStr = fs.ReadLine();
                while (true)
                {
                    readStr = fs.ReadLine();
                    if (readStr == null)
                        break;
                    if (readStr.Length > 30)
                    {
                        infoPlon[infoNumber] = int.Parse(readStr.Substring(readStr.IndexOf("Lo(") + 3, 8)) * 10;
                        infoPlat[infoNumber] = int.Parse(readStr.Substring(readStr.IndexOf("La(") + 3, 7)) * 10;
                        infoNumber++;
                        if (infoNumber >= INFO_POINT_NUM_MAX)
                        {
                            MessageBox.Show("To many data");
                            return;
                        }
                    }
                }
                fs.Close();
            }
        }
        public string[] AllRoad(string s)
        {
            s = s.ToLower();
            ArrayList rns = new ArrayList();
            
            for (int i = 0; i < dispatchs.Count; i++)
            {
                RoadType rd = (RoadType)dispatchs[i];
                string rdName = rd.roadName;
                string py = ChineseConvertor.Convert(rdName);
                if (!rns.Contains(rdName))
                {
                    if (rdName.Contains(s) || py.StartsWith(s))
                        rns.Add(rdName);
                }
            }
            string[] names = new string[rns.Count];
            for (int i = 0; i < rns.Count; i++)
            {
                names[i] = (string)rns[i];
            }

            return names;
        }

        public bool ViewStaion(string stName)
        {
            StationType st;
            string py1 = "";
            string py2 = "";
            for (int i = 0; i < stationNumber; i++)
            {
                st = (StationType)stations[i];
                py1 = ChineseConvertor.Convert(st.stationName);
                py2 = ChineseConvertor.StrConvertToPinyin(st.stationName).ToLower();
                if (st.stationName.Contains(stName) || 
                    py1.StartsWith(stName.ToLower())||
                    py2.StartsWith(stName.ToLower()))
                {
                    centerlon = st.lonDimi;
                    centerlat = st.latDimi;
                    divisor = 200;
                    return true;
                }
            }
            return false;
        }
        public void FocusOnRoad(string rdName,bool jumpTo)
        {
            int lon = 33000000, lat=110000000;
            long dis=long.MaxValue;
            selectedRoadName = rdName;
            FindStationsOfSelectedRoad(selectedRoadName);
            if (!jumpTo)
                return;
            StationType st;
            for (int i = 0; i < stationNumber; i++)
            {
                st = (StationType)stations[i];
                if (st.roadName == rdName)
                {
                    long distemp = Math.Abs((long)centerlon - (long)st.lonDimi) * Math.Abs((long)centerlon - (long)st.lonDimi) +
                        Math.Abs((long)centerlat - (long)st.latDimi) * Math.Abs((long)centerlat - (long)st.latDimi);
                    if (distemp < dis)
                    {
                        dis = distemp;
                        lon = st.lonDimi;
                        lat = st.latDimi;
                    }
                }
            }
            if (lon != 33000000)
            {
                centerlon = lon;
                centerlat = lat;
            }
        }

        public void Zoom(Point m, int div,bool smartZ)
        {
            if (smartZ)
            {
                CenterLon = m.X - (m.X - CenterLon) / Divisor * div;
                CenterLat = m.Y - (m.Y - CenterLat) / Divisor * div;
            }
            Divisor = div;
        }
        public string SearchDB(int lon, int lat)
        {
            string result = "";
            string type;
            string temp,phone;

            #region station
            StationType st;
            type = "车站:\r\n";
            for (int i = 0; i < stations.Count; i++)
            {
                st = (StationType)stations[i];
                if (InAreaCheck(lon, lat, st.lonDimi - st.LengthDini, st.latDimi - st.WidthDini,
                    st.lonDimi + st.LengthDini, st.latDimi + st.WidthDini))
                {
                    phone = st.sPhone;
                    if (phone != st.xPhone)
                        phone += ("-" + st.xPhone);
                    temp = st.roadName.PadRight(5, '　') + st.dispatchName.PadRight(8, '　') + " " +
                            st.stationName.PadRight(3, '　') + " ";
                    result += type + temp + st.mode.PadRight(4, ' ') + phone + "\r\n";
                    type = "";
                }
            }
            #endregion

            #region region
            RegionType rg;
            type = "区间:\r\n";
            for (int i = 0; i < regions.Count; i++)
            {
                rg = (RegionType)regions[i];
                int rglon, lonWd, rglat, latWd;
                rglon = GF.ToDimiDegree(rg.longitude);
                rglat = GF.ToDimiDegree(rg.latitude);
                lonWd = int.Parse(rg.lonwidth) * 100 / 6;
                latWd = int.Parse(rg.latwidth) * 100 / 6;
                rg = (RegionType)regions[i];
                if (InAreaCheck(lon, lat, rglon - lonWd, rglat - latWd,
                                        rglon + lonWd, rglat + latWd))
                {
                    result += type + rg.lineItem;
                }
            }
            #endregion

            #region QieHuan

            #endregion


            return result;
        }
        public void FindStationsOfSelectedRoad(string rdname)
        {
            StationType st;
            stationsOfSelectedRoad.Clear();
            for (int i = 0; i < stationNumber; i++)
            {
                st = (StationType)stations[i];
                if (st.roadName == rdname)
                {
                    stationsOfSelectedRoad.Add(st);
                }
            }
        }
        public bool InAreaCheck(int lon, int lat, int lon1, int lat1, int lon2, int lat2)
        {
            int temp;
            if(lon1>lon2)
            {
                temp=lon1;
                lon1=lon2;
                lon2=temp;
            }
            if(lat1>lat2)
            {
                temp=lat1;
                lat1=lat2;
                lat2=temp;
            }
            if (lon < lon1 || lon > lon2 || lat < lat1 || lat > lat2)
                return false;
            else
                return true;
        }
        #endregion



        /*
        public void FindRegionInDatabase()
        {
            XLSheet sheet1 = book1.Sheets["车站"];
            int i, j, count = 0;
            long progess;
            string sourceLonStr, sourceLatStr, targetLonStr, targetLatStr;
            int sourceLonInt, sourceLatInt, targetLonInt, targetLatInt;
            string sourceRoad, sourecDisp, targetRoad, targetDisp;
            int datasum = int.Parse(book1.Sheets["set"][10, 1].Value.ToString().Trim());

            int regioncount = 1;

            MYEXCEL.Excel.Application myexcel = new MYEXCEL.Excel.ApplicationClass();
            MYEXCEL.Excel.Workbook xbook = myexcel.Workbooks.Add(true);
            MYEXCEL.Excel.Worksheet xSheet = (MYEXCEL.Excel.Worksheet)xbook.ActiveSheet;
            myexcel.Visible = false;

            string pathstr = "C:\\Users\\wufali\\Desktop" + "\\" + "Region" + ".xls";
            if (File.Exists(pathstr))
            {
                File.Delete(pathstr);
            }
            myexcel.Cells[1, 1] = "车站1";
            myexcel.Cells[1, 2] = "经度1";
            myexcel.Cells[1, 3] = "纬度1";
            myexcel.Cells[1, 4] = "线路1";
            myexcel.Cells[1, 5] = "调度区段1";
            myexcel.Cells[1, 6] = "模式1";
            myexcel.Cells[1, 7] = "车站2";
            myexcel.Cells[1, 8] = "经度2";
            myexcel.Cells[1, 9] = "纬度2";
            myexcel.Cells[1, 10] = "线路2";
            myexcel.Cells[1, 11] = "调度区段2";
            myexcel.Cells[1, 12] = "模式2";

            for (i = 0; i < datasum; i++)
            {
                sourceLonStr = sheet1[i + 1, 6].Value.ToString().Trim();
                sourceLatStr = sheet1[i + 1, 7].Value.ToString().Trim();
                sourceLonInt = LonLatFormatChange(sourceLonStr, true);
                sourceLatInt = LonLatFormatChange(sourceLatStr, false);
                sourceRoad = sheet1[i + 1, 0].Value.ToString().Trim();
                sourecDisp = sheet1[i + 1, 1].Value.ToString().Trim();

                for (j = i + 1; j < datasum; j++)
                {
                    targetLonStr = sheet1[j + 1, 6].Value.ToString().Trim();
                    targetLatStr = sheet1[j + 1, 7].Value.ToString().Trim();
                    targetLonInt = LonLatFormatChange(targetLonStr, true);
                    targetLatInt = LonLatFormatChange(targetLatStr, false);
                    targetRoad = sheet1[j + 1, 0].Value.ToString().Trim();
                    targetDisp = sheet1[j + 1, 1].Value.ToString().Trim();

                    if (Math.Abs(targetLonInt - sourceLonInt) < 10000 & Math.Abs(targetLatInt - sourceLatInt) < 10000)
                    {
                        if (isInRegionAlready(sourceLonInt, sourceLatInt) || isInRegionAlready(targetLonInt, targetLatInt))
                            continue;
                        count++;

                        myexcel.Cells[regioncount + 1, 1] = sheet1[i + 1, 3].Value.ToString().Trim();
                        myexcel.Cells[regioncount + 1, 2] = sheet1[i + 1, 6].Value.ToString().Trim();
                        myexcel.Cells[regioncount + 1, 3] = sheet1[i + 1, 7].Value.ToString().Trim();
                        myexcel.Cells[regioncount + 1, 4] = sourceRoad;
                        myexcel.Cells[regioncount + 1, 5] = sourecDisp;
                        myexcel.Cells[regioncount + 1, 6] = sheet1[i + 1, 2].Value.ToString().Trim();
                        myexcel.Cells[regioncount + 1, 7] = sheet1[j + 1, 3].Value.ToString().Trim();
                        myexcel.Cells[regioncount + 1, 8] = sheet1[j + 1, 6].Value.ToString().Trim();
                        myexcel.Cells[regioncount + 1, 9] = sheet1[j + 1, 7].Value.ToString().Trim();
                        myexcel.Cells[regioncount + 1, 10] = targetRoad;
                        myexcel.Cells[regioncount + 1, 11] = targetDisp;
                        myexcel.Cells[regioncount + 1, 12] = sheet1[j + 1, 2].Value.ToString().Trim();

                        myexcel.Cells[regioncount + 1, 13] = Math.Abs(targetLonInt - sourceLonInt).ToString();
                        myexcel.Cells[regioncount + 1, 14] = Math.Abs(targetLatInt - sourceLatInt).ToString();
                        regioncount++;
                    }
                    progess = ((long)(datasum * 2 - 2 - i) * (i + 1)) * 1000 / (datasum * (datasum - 1));
                    backgroundWorker1.ReportProgress((int)progess);

                }
                //System.Threading.Thread.Sleep(100);
            }

            xbook.SaveAs(pathstr, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal, Missing.Value, Missing.Value, Missing.Value, Missing.Value, MYEXCEL.Excel.XlSaveAsAccessMode.xlNoChange, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
            MessageBox.Show("生成文件成功！");
            xbook = null;
            xSheet = null;
            myexcel.Quit();
            System.Runtime.InteropServices.Marshal.ReleaseComObject((object)myexcel);
            System.GC.Collect();

            return;
        }
        private bool isInRegionAlready(int lon1, int lat1)
        {
            int regionNumber = int.Parse(book1.Sheets["set"][11, 1].Value.ToString().Trim());
            int lon2, lat2;
            for (int i = 0; i < regionNumber; i++)
            {
                lon2 = LonLatFormatChange(book1.Sheets["线路选择区间"][i + 1, 2].Value.ToString().Trim(), true);
                lat2 = LonLatFormatChange(book1.Sheets["线路选择区间"][i + 1, 3].Value.ToString().Trim(), false);
                if (Math.Abs(lon1 - lon2) < 13333 & Math.Abs(lat1 - lat2) < 13333)
                {
                    return true;
                }
            }
            return false;
        }
          
                 private void FindTooFarPoint(DataSet resultdataset, int numrows)
        {
            string roadname = resultdataset.Tables["export"].Rows[1]["所属线路名称"].ToString().Trim();
            int[] indexforcurrentroad = new int[300];
            for (int i = 0; i < 300; i++)
            {
                indexforcurrentroad[i] = 0;
            }
            int wholeStationNumber = 0;
            if (groupBox1.Enabled == true)
                wholeStationNumber = int.Parse(book1.Sheets["set"][10, 1].Value.ToString().Trim());
            int currenstationnumber = 0;
            for (int i = 0; i < wholeStationNumber; i++)
            {
                if (book1.Sheets["车站"][i + 1, 0].Value.ToString().Trim() == roadname)
                {
                    indexforcurrentroad[currenstationnumber] = i;
                    currenstationnumber++;
                    if (currenstationnumber == 300)
                    {
                        MessageBox.Show("station buffer no enough");
                        break;
                    }
                }
            }
            int intlon1, intlat1, intlon2, intlat2;
            string strlon1, strlat1, strlon2, strlat2;
            if (numrows > 0)
            {
                for (int i = 0; i < numrows; i++)
                {
                    strlon1 = resultdataset.Tables["export"].Rows[i]["经度"].ToString();
                    strlat1 = resultdataset.Tables["export"].Rows[i]["纬度"].ToString();
                    intlon1 = LonLatFormatChange(strlon1, true) / 10;
                    intlat1 = LonLatFormatChange(strlat1, false) / 10;
                    intlon1 = intlon1 * 6 / 10;
                    intlat1 = intlat1 * 6 / 10;
                    if (strlon1 == "0" || strlat1 == "0")
                        continue;
                    for (int j = 0; j < currenstationnumber; j++)
                    {
                        strlon2 = book1.Sheets["车站"][indexforcurrentroad[j] + 1, 6].Value.ToString().Trim();
                        strlat2 = book1.Sheets["车站"][indexforcurrentroad[j] + 1, 7].Value.ToString().Trim();
                        intlon2 = LonLatFormatChange(strlon2, true) / 10;
                        intlat2 = LonLatFormatChange(strlat2, false) / 10;
                        intlon2 = intlon2 * 6 / 10;
                        intlat2 = intlat2 * 6 / 10;
                        long dis = (long)Math.Abs(intlon1 - intlon2) * (long)Math.Abs(intlon1 - intlon2) +
                              (long)Math.Abs(intlat1 - intlat2) * (long)Math.Abs(intlat1 - intlat2);
                        if (dis < 116640000)
                        {
                            break;
                        }

                        if (j == (currenstationnumber - 1))
                        {
                            string pathstr = "C:\\Users\\wufali\\Desktop" + "\\" + "TooFarPoint.txt";
                            //if (File.Exists(pathstr))
                            //{
                            //    File.Delete(pathstr);
                            //}
                            using (FileStream fs1 = new FileStream(pathstr, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                            {
                                StreamWriter w1 = new StreamWriter(fs1);
                                fs1.Seek(0, SeekOrigin.End);
                                w1.WriteLine(roadname + i.ToString() + ":" + strlon1 + "," + strlat1);
                                w1.Close();
                                fs1.Close();
                            }
                            return;
                        }
                    }
                }
            }
        }
  private void button1_Click(object sender, EventArgs e)
        {
            if (groupBox1.Enabled == false)
            {
                MessageBox.Show("DataBase No Found");
                return;
            }
            OpenFileDialog frm1 = new OpenFileDialog();
            frm1.Filter = "数据库(.mdb)|*.mdb";
            frm1.Title = "请选择上行数据库文件";
            frm1.Multiselect = true;
            if (frm1.ShowDialog() == DialogResult.OK)
            {
                foreach (string fn in frm1.FileNames)
                {
                    string connstr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fn;
                    OleDbConnection conn = new OleDbConnection(connstr);
                    OleDbDataAdapter dscmd = new OleDbDataAdapter();
                    DataSet resultdataset = new DataSet();

                    string strselect = "Select 经度,纬度,所属线路名称 From export Order By 序号 Desc";
                    OleDbCommand selectcommand = new OleDbCommand(strselect, conn);
                    selectcommand.CommandType = CommandType.Text;

                    try
                    {
                        conn.Open();
                        dscmd.SelectCommand = selectcommand;
                        int numrows = dscmd.Fill(resultdataset, "export");

                        FindTooFarPoint(resultdataset, numrows);
                    }
                    catch (Exception er)
                    {
                        MessageBox.Show(er.Message.ToString());
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
                MessageBox.Show("Searching Finished");
            }
        }
*/

//end************************************************************
    }
}
